package com.jy.oms.framework.util;

import org.springframework.core.ResolvableType;

/**
 * 泛型util
 *
 * @author liuquan
 */
public final class GenericClassUtil {

    /**
     * 获取对象泛型接口参数类型
     */
    public static Class resolveGenericClass(Object obj, Class<?> clazz) {
        ResolvableType resolvableType = resolveGenericClassType(obj, clazz);
        return resolvableType != null ? resolvableType.resolveGeneric(0) : null;
    }

    public static ResolvableType resolveGenericClassType(Object obj, Class<?> clazz) {
        ResolvableType resolvableType = ResolvableType.forInstance(obj);
        ResolvableType resolvableSuperType = resolveSuperGeneric(resolvableType, clazz);
        if (resolvableSuperType != null) {
            return resolvableSuperType;
        }

        ResolvableType resolvableInterfaceType = resolveInterfaceGeneric(resolvableType, clazz);
        if (resolvableInterfaceType != null) {
            return resolvableInterfaceType;
        }

        return null;
    }

    /**
     * 获取指定对象继承类泛型参数
     *
     * @param resolvableType 指定对象
     * @param clazz          指定继承类
     */
    public static ResolvableType resolveSuperGeneric(ResolvableType resolvableType, Class<?> clazz) {
        ResolvableType superType = resolvableType.getSuperType();
        if (superType == null || superType.getRawClass() == Object.class) {
            return null;
        }

        if (superType.getRawClass() == clazz) {
            return superType;
        }

        ResolvableType interfaceGeneric = resolveInterfaceGeneric(superType, clazz);
        if (interfaceGeneric != null) {
            return interfaceGeneric;
        }

        return resolveSuperGeneric(superType, clazz);
    }

    /**
     * 获取指定接口泛型参数
     *
     * @param resolvableType 指定对象
     * @param clazz          指定接口
     */
    public static ResolvableType resolveInterfaceGeneric(ResolvableType resolvableType, Class<?> clazz) {
        ResolvableType[] interfaces = resolvableType.getInterfaces();
        for (ResolvableType anInterface : interfaces) {
            if (anInterface.getRawClass() == clazz) {
                return anInterface;
            }
        }

        for (ResolvableType anInterface : interfaces) {
            ResolvableType returnResolvableType = resolveInterfaceGeneric(anInterface, clazz);
            if (returnResolvableType != null) {
                return returnResolvableType;
            }
        }

        return null;
    }
}
